#include <ClanLib-2.0/ClanLib/core.h>
#include <ClanLib-2.0/ClanLib/display.h>

#include "world.h"
#include "unit.h"

World::World(CL_DisplayWindow &window) : quit(false)
{
	this->window = window;

	gc = window.get_gc();

	CL_Slot slot_quit = window.sig_window_close().connect(this, &World::OnWindowClose);

	resources = CL_ResourceManager("resources.xml");

	slotKeyDown = window.get_ic().get_keyboard().sig_key_down().connect(this, &World::OnKeyDown);
	slotMouseDown = window.get_ic().get_mouse().sig_key_down().connect(this, &World::OnMouseDown);
	slotMouseUp = window.get_ic().get_mouse().sig_key_up().connect(this, &World::OnMouseUp);
	slotMouseMove = window.get_ic().get_mouse().sig_pointer_move().connect(this, &World::OnMouseMove);

	//LoadLevel (TODO: SOCK'S HERE)
	LoadLevel();

	//run the main game loop
	loop();
}

World::~World()
{
	std::list<Object*>::iterator it;
	for(it = objects.begin(); it != objects.end(); ++it)
		delete (*it);
}

void World::LoadLevel()
{
	Unit *utest = new Unit(this);
	utest->SetHP(1);
	utest->SetPos(200, 200);
	utest->Select(); //Select our unit
	AddUnit(utest);

	Unit *utwo = new Unit(this);
	utwo->SetHP(1);
	utwo->Deselect();
	utwo->SetPos(500, 500);
	AddUnit(utwo);
}

void World::AddObject(Object *obj)
{
      objects.push_back(obj);
}

void World::AddUnit(Unit *unt) //Test {iBoris}
{
	objects.push_back(unt);
	units.push_back(unt);
}

void World::loop()
{
	while (!window.get_ic().get_keyboard().get_keycode(CL_KEY_ESCAPE))
	{
		if (quit)
			break;

		update();
		draw();

		window.flip(1);
		CL_DisplayMessageQueue::process();
	}
}

void World::update()
{
	float time = FPS();

	std::list<Object*>::iterator it;
	for(it = objects.begin(); it != objects.end(); )
	{
		if((*it)->update(time) == false)
		{
			delete (*it);
			it = objects.erase(it);
		}
		else
			++it;
	}
}

float World::FPS()
{
	static float lastTime = 0;

	float newTime = (float)CL_System::get_time();
	if(lastTime == 0)
		lastTime = newTime;

	float deltaTime = (newTime - lastTime) / 1000.0f;
	lastTime = newTime;

	return deltaTime;
}

void World::draw()
{
	std::list<Object*>::iterator it;
	for(it = objects.begin(); it != objects.end(); ++it)
		(*it)->draw();
}

bool World::HitCheck(CL_CollisionOutline *outline, Object *owner)
{
	std::list<Object*>::iterator it;
	for (it = objects.begin(); it != objects.end(); ++it)
		if ((*it) != owner)
			if ((*it)->HitCheck(outline, owner))
				return true;
	return false;

}

void World::Danger(int x, int y, const Object *owner)
{
	std::list<Unit*>::iterator it;
	for(it = units.begin(); it != units.end(); ++it)
	{
	      Unit *unit = (*it);
	      if (unit != owner && unit->HitCheck(x, y))
			unit->Damage(1);
	}
}

void World::OnKeyDown(const CL_InputEvent &key, const CL_InputState &state)
{

}

void World::OnMouseDown(const CL_InputEvent &key, const CL_InputState &state)
{
	if (key.id == CL_MOUSE_RIGHT)
	{
		std::list<Unit*>::iterator it;		//Units - test list in world {iBoris}
		for (it = units.begin(); it != units.end(); ++it)
			if ((*it)->IsSelected())
				(*it)->SetDest(key.mouse_pos.x, key.mouse_pos.y);
	}

	if (key.id == CL_MOUSE_LEFT)
	{
		std::list<Unit*>::iterator it;
		for (it = units.begin(); it != units.end(); ++it)
			if ((*it)->IsSelected())
				(*it)->Fire();
	}
}

void World::OnMouseUp(const CL_InputEvent &key, const CL_InputState &state)
{

}

void World::OnMouseMove(const CL_InputEvent &key, const CL_InputState &state)
{
	std::list<Unit*>::iterator it;
	for (it = units.begin(); it != units.end(); ++it) //Non-illusion test {iBoris}
		if ((*it)->IsSelected())
			(*it)->SetTurretDest(key.mouse_pos.x, key.mouse_pos.y);
}

void World::OnWindowClose()
{
	quit = true;
}
